iT邦幫忙

2024 iThome 鐵人賽

DAY 10
0
Modern Web

與 AI 一起開發 Side Project 吧!系列 第 10

Day10 — 初試啼聲 | 手繪交給 AI 不滿意,那…畫漂亮一點總行了吧?

  • 分享至 

  • xImage
  •  

上一次我們將手稿交給 AI 進行分析生成,但結果並不令人滿意,或者嚴格說起來,令人不滿意。感覺 AI 只做了一半,拿到了「半成品」而已。

然而,這不能只怪 AI ,問題不僅僅在於「圖片」的部分,正如之前提到的 AI 指令技巧,之前下的指令並不夠明確,只提供了粗略的要求:「要做一個記帳 App(使用 React)」,這樣的指令仍遠遠不夠具體。

接下來,我們需要進行調整和修正,探討如何搭配設計稿來制定更具體的指令,做到「一步到位」的目標!

美化一下

畫一下線框稿看看

上一次我們拿手稿餵給 AI,並不是很滿意,AI 給的答案有點粗糙,不是個「production-ready」的程式碼,無法直接拿來用呀!

自己還要修修補補,幾乎要整個重寫,根本也沒有比較快。

既然如此,還能做得更好嗎? 當然可以,從 AI 生成的程式碼來看,再看一下我們給的圖,可以初步推論說:AI 沒有很懂我們想做什麼,並沒有清晰了解設計稿的需求。

因此,只好花點時間,用 Miro 把手稿給美化一下,以更清晰的線條加強表達,再餵給 AI 試試看吧!

以下是努力生出來的線框稿,雖然不是很美觀,不過已經很夠了,遠比先前的設計稿要來得清楚許多。

努力了一番之後,線框圖總算生出來了,看起來表達清晰許多了。雖然是有點簡單簡陋,不過應該是可以遠比上一次的手繪稿,給出更好的結果吧?

https://ithelp.ithome.com.tw/upload/images/20240920/20168308IuWMrHOHOO.jpg

此外,除了以上設計圖以外,還補了一些比較明確的指令給 AI 參考。

等了一會… AI 生成了以下程式碼:

import React, { useState } from 'react';

const AccountingApp: React.FC = () => {
  const [input, setInput] = useState('');
  const [records, setRecords] = useState<number[]>([]);

  const handleInput = (value: string) => {
    if (value === 'OK') {
      const amount = parseFloat(input);
      if (!isNaN(amount)) {
        setRecords([...records, amount]);
        setInput('');
      }
    } else {
      setInput(input + value);
    }
  };

  const getTotal = () => {
    return records.reduce((sum, record) => sum + record, 0);
  };

  return (
    <div className="max-w-sm mx-auto">
      <div className="bg-gray-200 p-4 mb-4">
        <div className="text-right text-3xl mb-4">${getTotal().toFixed(2)}</div>
        <div className="text-right text-4xl">${input}</div>
      </div>
      <div className="grid grid-cols-4 gap-2">
        {[7, 8, 9, 'AC', 4, 5, 6, '⌫', 1, 2, 3, 'OK', '.', 0, '+'].map((key) => (
          <button
            key={key}
            className="bg-white text-2xl p-4 rounded shadow"
            onClick={() => handleInput(key.toString())}
          >
            {key}
          </button>
        ))}
      </div>
      <ul className="mt-4">
        {records.map((record, index) => (
          <li key={index}>${record.toFixed(2)}</li>
        ))}
      </ul>
    </div>
  );
};

export default AccountingApp;

Claude.ai 的 preview 功能預覽一下,做出來的成果好多了。

至少功能真的可以用,至少基本數字的輸入後,再按 OK 就能記帳了,且長得跟線框稿有點像。

https://ithelp.ithome.com.tw/upload/images/20240920/20168308vnoMYm1qaG.jpg

嗯…就有點像而已。 😭

精美設計圖

線框稿餵給 AI 後,生成的程式碼完成度已經蠻不錯了,但還想要更好。

希望 AI 可以照著設計稿「照抄」,幫我做到一步到位。心中 OS 疑問:到底能不能單純靠著「指令和設計稿」,就產出可以直接用的程式碼?

雖然不是很有信心,但不試也不會知道,但作為開發者也不太會畫畫,這時候只好請設計師幫忙畫一下囉。(撒嬌一下)

總之設計折騰了一番,總算產出了如下的設計圖,好看多了 :)

https://ithelp.ithome.com.tw/upload/images/20240920/20168308z9PWYl5QNd.jpg

除了圖稿變得更漂亮以外,指令也要更精進具體,輸入的指令如下:

 幫我依照設計稿,製作記帳 App。
- 最上方之金額,為記帳金額的總和
- 可以用數字鍵盤輸入數字
- AC 可以歸零
- Backspace icon 的按鍵可將數字倒退
- 按下 OK 即可紀錄該筆帳目

稍等一會,AI 生成了這樣的程式碼,程式碼有點長,相比第一次產出的很完整!

import React, { useState } from "react";

interface DisplayProps {
  total: number;
  currentAmount: string;
}

const Display: React.FC<DisplayProps> = ({ total, currentAmount }) => {
  return (
    <div className="bg-white p-4 rounded-t-lg">
      <div className="text-3xl font-bold text-right mb-2">${total}</div>
      <div className="text-2xl text-right">${currentAmount}</div>
    </div>
  );
};

interface KeypadProps {
  onInput: (value: string) => void;
  onClear: () => void;
  onBackspace: () => void;
  onOk: () => void;
}

const Keypad: React.FC<KeypadProps> = ({
  onInput,
  onClear,
  onBackspace,
  onOk
}) => {
  const buttons = [
    "7",
    "8",
    "9",
    "AC",
    "4",
    "5",
    "6",
    "⌫",
    "1",
    "2",
    "3",
    "OK",
    ".",
    "0",
    "+",
    ""
  ];

  return (
    <div className="grid grid-cols-4 gap-2 bg-gray-800 p-4 rounded-b-lg">
      {buttons.map((btn, index) => (
        <button
          key={index}
          className={`p-4 text-xl font-bold rounded ${
            btn === "OK"
              ? "bg-blue-500 text-white col-span-2"
              : btn === "AC"
              ? "bg-red-500 text-white"
              : btn === "⌫"
              ? "bg-yellow-500 text-white"
              : "bg-gray-700 text-white"
          }`}
          onClick={() => {
            if (btn === "AC") onClear();
            else if (btn === "⌫") onBackspace();
            else if (btn === "OK") onOk();
            else onInput(btn);
          }}
        >
          {btn}
        </button>
      ))}
    </div>
  );
};

interface HistoryListProps {
  history: number[];
}

const HistoryList: React.FC<HistoryListProps> = ({ history }) => {
  return (
    <div className="mt-4 bg-white p-4 rounded-lg">
      <h2 className="text-xl font-bold mb-2">記帳歷史</h2>
      <ul>
        {history.map((amount, index) => (
          <li key={index} className="text-lg">
            ${amount}
          </li>
        ))}
      </ul>
    </div>
  );
};

const App: React.FC = () => {
  const [currentAmount, setCurrentAmount] = useState<string>("0");
  const [total, setTotal] = useState<number>(0);
  const [history, setHistory] = useState<number[]>([]);

  const handleInput = (value: string) => {
    if (currentAmount === "0") {
      setCurrentAmount(value);
    } else {
      setCurrentAmount(currentAmount + value);
    }
  };

  const handleClear = () => {
    setCurrentAmount("0");
  };

  const handleBackspace = () => {
    if (currentAmount.length > 1) {
      setCurrentAmount(currentAmount.slice(0, -1));
    } else {
      setCurrentAmount("0");
    }
  };

  const handleOk = () => {
    const amount = parseFloat(currentAmount);
    setTotal(total + amount);
    setHistory([...history, amount]);
    setCurrentAmount("0");
  };

  return (
    <div className="max-w-md mx-auto mt-10 p-4 bg-gray-100 rounded-lg shadow-lg">
      <Display total={total} currentAmount={currentAmount} />
      <Keypad
        onInput={handleInput}
        onClear={handleClear}
        onBackspace={handleBackspace}
        onOk={handleOk}
      />
      <HistoryList history={history} />
    </div>
  );
};

export default App;

用了 Preview 功能來預覽一下,看起來該做到的功能都有做到。雖然畫面鍵盤排版有點怪怪的,但瑕不掩瑜,已經很好了!

歸零、刪除和 OK 之類的都有做到,顏色也有填上去,挺好的!

https://ithelp.ithome.com.tw/upload/images/20240920/20168308xHcKmu1RMq.jpg

總結

你清楚,AI 才會明瞭

由以上的生成範例,以及自己使用生成式 AI 的經驗,大致上得出了這樣的結論:「自己覺得表達夠清楚,AI 才會清楚。」

之前畫的手稿雖然「足以溝通」,但並不是個夠好的想法載體,無法「精準」地表達想法。而在經過圖形的精準演進之後,很明顯 AI 的生成結果,已經相當接近圖案所表達的需求了。

圖文並茂

除了圖案清楚以外,搭配的文字指令也要清晰且具體,最好是不要讓 AI 用猜的,能夠用文字表達的需求,盡量寫清楚說明白。

有了乾淨清楚的設計稿,搭配具體清晰的需求指令,就能大幅提高 AI 生成的精準度呦!


上一篇
Day9 — 初試啼聲 | 畫了草稿,就直接交給 AI 生出程式碼
下一篇
Day11 — 初試啼聲 | 既然沒法一步到位,怎麼做? 先做好心態調整吧
系列文
與 AI 一起開發 Side Project 吧!30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言